package com.rabbiter.association.aspect;

import com.rabbiter.association.entity.RequestLog;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * 请求日志切面类
 * 用于拦截Controller层方法调用并记录日志到Elasticsearch
 */
@Aspect
@Component
@RequiredArgsConstructor
public class RequestLoggingAspect {

    // 用于操作Elasticsearch的Spring Data组件
    private final ElasticsearchOperations elasticsearchOperations;

    /**
     * 环绕通知方法，拦截所有Controller包下的方法执行
     * @param joinPoint 连接点对象，包含被拦截方法的信息
     * @return 被拦截方法的执行结果
     * @throws Throwable 如果被拦截方法抛出异常
     */
    @Around("execution(* com.rabbiter.association.controller..*(..))")
    public Object logRequest(ProceedingJoinPoint joinPoint) throws Throwable {
        // 记录方法开始执行的时间戳
        long startTime = System.currentTimeMillis();

        // 创建请求日志对象
        RequestLog log = new RequestLog();
        log.setTimestamp(LocalDateTime.now());  // 设置当前时间
        log.setClassName(joinPoint.getTarget().getClass().getName());  // 设置类全限定名
        log.setMethodName(joinPoint.getSignature().getName());  // 设置方法名

        // 将方法参数数组转为字符串格式存储
        log.setArgs(Arrays.toString(joinPoint.getArgs()));

        try {
            // 执行目标方法并获取返回值
            Object result = joinPoint.proceed();
            long endTime = System.currentTimeMillis();

            // 设置成功执行的日志信息
            log.setExecutionTime(endTime - startTime);  // 计算方法执行耗时(毫秒)
            log.setSuccess(true);  // 标记为成功执行
            log.setResponse(result.toString());  // 将返回值转为字符串存储

            // 将日志保存到Elasticsearch
            elasticsearchOperations.save(log);

            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();

            // 设置执行失败的日志信息
            log.setExecutionTime(endTime - startTime);  // 计算方法执行耗时
            log.setSuccess(false);  // 标记为执行失败
            log.setError(e.getMessage());  // 记录异常信息

            // 将错误日志保存到Elasticsearch
            elasticsearchOperations.save(log);

            // 重新抛出异常，保持原有异常处理流程
            throw e;
        }
    }
}